package com.uxwine.alarm.alert;

import com.nny.alarm.alert.AlertActivity;
import com.uxwine.alarm.Alarm;
import com.uxwine.alarm.AlarmCore;
import com.uxwine.alarm.AlertMgr;
import com.uxwine.alarm.Cmd;
import com.uxwine.alarm.Settings;
import com.uxwine.alarm.Snooze;
import com.uxwine.util.Log;

import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

public class AlarmService extends Service implements AlarmEffect.OnEffectListener
{
    private Alarm mCurrentAlarm;
    private long mStartTime;
    private boolean mCurrentStates = true;    
    private AlarmEffect mEffect;
    
    // Internal messages
    private static final int MSG_KILLER 		= 1;
    private static final int MSG_FOCUS_CHANGE 	= 2;  
    

    @Override
    public void onCreate() 
    {
    	mEffect = new AlarmEffect(this);
    	mEffect.init(this);
        AlarmWakeLock.getInstance(this).acquire();
    }

    @Override
    public void onDestroy()
    {
        stop();    
        mEffect.uninit();
        AlarmWakeLock.getInstance(this).release();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
    {
        // No intent, tell the system not to restart us.
        if (intent == null) 
        {
            stopSelf();
        	Log.d("new-zzm", "AlarmService.stopSelf in onStartCommand...");
            return START_NOT_STICKY;
        }
        final String action = intent.getAction();
        if(action.equals(Cmd.ACTION_ALARM_ALERT))
        {
        	return onAlarmAlert(intent);
        }

        return START_STICKY;
    }
    
    protected int onAlarmAlert(Intent intent)
    {
		Log.d("new-zzm", "onAlarmAlert: start...");
    	final Alarm alarm = intent.getParcelableExtra(Cmd.Alert.EXTRA_ALARM);

        // zzm: No alarm, stop and tell the system not to restart us.
        if (alarm == null) 
         {
             Log.d("new-zzm", "AlarmService failed to parse the alarm from the intent");
             stopSelf();
             return START_NOT_STICKY;
         }

         // zzm: 如果当前还在响铃，改变通知栏的状态：
         // 1.让用户知道之前的闹钟已经提醒过了
         // 2.点击后进入闹钟的设置界面，用户可以设置该闹钟
         if (mCurrentAlarm != null) 
         {
             Log.d("new-zzm", "AlarmService showTimeout(mCurrentAlarm)");
         	AlertMgr.getInstance(this).showTimeout(mCurrentAlarm);
         }

         // zzm: 开始闹（影响等效果）
         play(alarm);
         mCurrentAlarm = alarm;
         
         // zzm: 打开闹钟界面
         Intent i = new Intent(this, AlertActivity.class);
         i.putExtra(Cmd.Alert.EXTRA_ALARM, alarm);
         i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(i);
         return START_STICKY;
	}
    
    private void play(Alarm alarm) 
    {
    	// 停掉先前的闹钟
        stop();
        // 开始当前闹钟的效果
        mEffect.play(alarm);
        // 超时后结束闹钟
        enableKiller(alarm);
        // 记录闹钟开始的时间
        mStartTime = System.currentTimeMillis();
    }

    /**
     * Stops alarm audio and disables alarm if it not snoozed and not
     * repeating
     */
    public void stop() 
    {
        Log.d("zhangzhongming", "AlarmService.stop()");
    	Log.f("snooze", "AlarmService.stop()");
        if (mEffect.isPlaying()) 
        {
        	//通知别人处理懒人模式或者Repeat情况。
            //Intent alarmDone = new Intent(AlarmUtil.ACTION_ALARM_DONE);
            //sendBroadcast(alarmDone);
            
            //停止影响效果
            mEffect.stop();
        }
        //清除结束响铃的消息【即enableKiller延迟发送的消息】。
        disableKiller();
    }

    /**
     * Kills alarm audio after ALARM_TIMEOUT_SECONDS, so the alarm
     * won't run all day.
     *
     * This just cancels the audio, but leaves the notification
     * popped, so the user will know that the alarm tripped.
     */
    private void enableKiller(Alarm alarm) 
    {
    	Log.d("new-zzm", "AlarmService.enableKiller");
    	int timeout = AlarmContext.getInstance(this).getRingTimeOut();
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_KILLER, alarm), timeout);
    }

    private void disableKiller() 
    {
    	Log.d("new-zzm", "AlarmService.disableKiller");
        mHandler.removeMessages(MSG_KILLER);
    }

	@Override
	public void onAudioFocusChange(int focusChange)
	{
		mHandler.obtainMessage(MSG_FOCUS_CHANGE, focusChange, 0).sendToTarget();
	}

	@Override
	public void onCallStateChanged(int state, String ignored)
	{
     	AlertMgr.getInstance(this).showTimeout(mCurrentAlarm);
    	Log.d("new-zzm", "AlarmService.stopSelf in onCallStateChanged...");
        stopSelf();
	}
	
	private Handler mHandler = new Handler() 
    {
        public void handleMessage(Message msg)
        {
            switch (msg.what) 
            {
            case MSG_KILLER:
            	Log.d("zhangzhongming", "*********** Alarm killer triggered ***********");
            	final Alarm alarm = (Alarm)msg.obj;
            	final Settings s = Settings.getInstance(AlarmService.this);
        		final long d = s.getSnoozeDuration(Settings.SNOOZE_DURATION_DEFAULT);
        		alarm.trigger += d * 1000L * 60L;
            	if(!AlarmCore.snoozeAlarm(AlarmService.this, alarm, true))
            	{
	            	Log.d("new-zzm", "AlarmService.stopSelf in handler...");
	                stopSelf();
            	}
                break;
            case MSG_FOCUS_CHANGE:
            	handleAudioFucusChange(msg.arg1);
                break;
            default:
            	break;
            }
        }
    };
	
	private void handleAudioFucusChange(int foucsChange)
	{
		switch (foucsChange) 
		{
        case AudioManager.AUDIOFOCUS_LOSS:
            
            if(mEffect.isLoss()) 
            {
                stop();
            }
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            
            if(mEffect.isLoss()) 
            {
                mEffect.pause();
                mCurrentStates = false;
            }
            break;
        case AudioManager.AUDIOFOCUS_GAIN:
            
            if(mEffect.isPlaying() && !mCurrentStates) {
                play(mCurrentAlarm); 
            } 
            break;
        default:
            
            break;
		}                 
	}

}
